﻿/*-------------------------------------------------------------------------
* 命名空间: SiliconSelect.Common/SocketServer
* 类       名: SocketServer
* 功      能:  TD
* 时      间:  2023/6/29 10:02:27
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using DocumentFormat.OpenXml.Office.CustomUI;
using log4net.Core;
using SiliconSelect.Base;
using SiliconSelect.BLL;
using SiliconSelect.Extensions;
using SiliconSelect.Models;
using SiliconSelect.PlcComunication;
using SiliconSelect.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.DirectoryServices.ActiveDirectory;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
using System.Printing;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Threading;

namespace SiliconSelect.Common
{
    public class SocketServer
    {
        public SocketServer(SlaveState slaveState)
        {
            _slaveState = slaveState;
            if (_slaveState.SlaveName!.Contains("崩边隐裂"))
            {
                _clientName = "崩边隐裂";
            }
            else if (_slaveState.SlaveName!.Contains("脏污"))
            {
                _clientName = "脏污";
            }
            else if (_slaveState.SlaveName!.Contains("尺寸"))
            {
                _clientName = "尺寸";
            }
            else if (_slaveState.SlaveName!.Contains("3D"))
            {
                _clientName = "3D";
            }
            else if (_slaveState.SlaveName!.Contains("国产电阻率"))
            {
                _clientName = "国产电阻率";
            }
            else if (_slaveState.SlaveName!.Contains("电阻率"))
            {
                _clientName = "电阻率";
            }
            _clientIp = _slaveState.IP;
            _clientPort = _slaveState.Port + _slaveState.PortAdd;

        }
        /// <summary>
        /// 检测到断连的次数,默认是0
        /// </summary>
        public int DisConnectedCount = 0;

        public bool Calibration3DIsOK = false;// 3D标定是否成功
        public string? Calibration3DErrorInfo = "3D相机标定,视觉未返回结果!"; // 3D标定错误原因.

        /// <summary>
        /// 最后一次获取消息的时间
        /// </summary>
        private DateTime _lastMsgTime;

        public DateTime LastMsgTime
        {
            get { return _lastMsgTime; }
            set { _lastMsgTime = value; }
        }

        /// <summary>
        /// pcName
        /// </summary>
        public string? pcName;
        /// <summary>
        /// CameraName
        /// </summary>
        public string? cameraName;

        public SlaveState _slaveState;

        /// <summary>
        /// 客户端名称(从站名称)
        /// </summary>
        private string? _clientName;
        /// <summary>
        /// 客户端Ip(从站Ip)
        /// </summary>
        private string? _clientIp;
        /// <summary>
        /// 负责和客户端连接的端口号
        /// </summary>
        private int _clientPort;

        private TcpListener? _listener;

        /// <summary>
        /// Sockeet服务是否打开
        /// </summary>
        private bool ServerIsOpen = false;

        /// <summary>
        /// 清空消息是否收到回复
        /// </summary>
        public bool ClearResponseIsOk = false;


        /// <summary>
        /// 客户端是否在线
        /// </summary>
        public bool _isAlive { get; set; }

        // 是否关闭刷新
        public bool CloseRefresh { get; set; } = false;

        /// <summary>
        /// 读取消息任务的标志位
        /// </summary>

        /// <summary>
        /// 已经连接的TcpClientConnected对象,如果没有连接,就是null.
        /// 我现在就是每个TcpServer负责一个客户端,就是说如果之前已经有连接了,就先关闭掉
        /// </summary>
        private TcpClient? TcpClientConnected = null;

        public CancellationTokenSource _tokenListener = new CancellationTokenSource();
        public CancellationTokenSource _tokenAsyncRead = new CancellationTokenSource();

        /// <summary>
        /// TCP服务器开启,开始监听
        /// </summary>
        /// <returns></returns>
        public async Task StartServerAsync(CancellationTokenSource tokenParent)
        {
            try
            {
                ServerIsOpen = true;
                _listener = new TcpListener(IPAddress.Any, _clientPort);
                _listener.ExclusiveAddressUse = false;
                _listener.Start();
                while (!tokenParent.IsCancellationRequested && ServerIsOpen)
                {
                    string msg = "";
                    _slaveState.ReadyStatus = true;
                    LogHelper.WriteLog(LogType.Info, $"负责从站 ({_clientName}) 的服务器已经开启..");
                    TcpClient client = await _listener.AcceptTcpClientAsync(_tokenListener.Token);
                    // 任务结束有几种情况呢,一个是主动结束,一个是被动结束,出现了异常
                    // 如果是主动结束, 就说明传递过来的这个Token是取消掉的,就直接退出去就行了
                    // 如果不是主动结束的就继续后面的任务.
                    if (!ServerIsOpen || tokenParent.IsCancellationRequested)
                    {
                        break;
                    }
                    // 先判断IP地址是否正确
                    IPAddress clientIpAddress = ((IPEndPoint)client.Client.RemoteEndPoint!).Address;
                    if (clientIpAddress.ToString() != _clientIp)
                    {
                        msg = $"{clientIpAddress} 连接上来了,因为从站({_clientName})设置的IP地址为{_clientIp},所以连接不予以处理";
                        LogHelper.WriteLog(LogType.Warn, msg);
                        //continue; 这里先理睬一下.
                    }
                    if (TcpClientConnected != null)
                    {
                        TcpClientConnected?.Dispose();
                        TcpClientConnected?.Close();
                        TcpClientConnected = null;
                    }
                    TcpClientConnected = client;
                    _isAlive = true;
                    _slaveState.ConnectedStatus = "已连接";
                    DisConnectedCount = 0; // 将断连次数复位
                    LastMsgTime = DateTime.Now;
                    // 到这里就连接成功了,连接成功以后,你要判断如果之前已经有连接,要将之前的连接关闭掉.
                    msg = $"从站 {_clientName},  {clientIpAddress} 已经连接,开始收发消息,通知PLC服务重启";
                    switch (_clientName)
                    {
                        case "尺寸":
                            pcName = "PC1";
                            cameraName = "0";
                            break;
                        case "左崩":
                            pcName = "PC2";
                            cameraName = "2";
                            break;
                        case "右崩":
                            pcName = "PC2";
                            cameraName = "3";
                            break;
                        case "前崩":
                            pcName = "PC2";
                            cameraName = "0";
                            break;
                        case "后崩":
                            pcName = "PC2";
                            cameraName = "1";
                            break;
                        case "3D":
                            pcName = "PC3";
                            cameraName = "0";
                            break;
                        case "下脏污":
                            pcName = "PC4";
                            cameraName = "0";
                            break;
                        case "上脏污":
                            pcName = "PC4";
                            cameraName = "1";
                            break;
                        case "隐裂":
                            pcName = "PC5";
                            cameraName = "0";
                            break;
                        default:
                            break;
                    }
                    if (_clientName == "国产电阻率")
                    {
                        await Task.Run(async () =>
                         {
                             // 先停止设备
                             await SendMsgAsync(MsgPackHelper.GetStopOperateMsgSend(), isMainLog: true);
                             await Task.Delay(100);
                             // 设置皮带速度
                             await SendMsgAsync(MsgPackHelper.GetBeltSpeedMsgSend(), isMainLog: true);
                             await Task.Delay(100);


                             // 发送初始化消息,初始化完成之后,再进行后续的操作.
                             await SendMsgAsync(MsgPackHelper.GetInitMsgSend(), isMainLog: true);
                             await Task.Delay(100);

                             // 开启设备
                             await SendMsgAsync(MsgPackHelper.GetStartOperateMsgSend(), isMainLog: true);
                         });


                    }
                    //else
                    //{
                    //    DataResult res = PlcCommunication.Instance.RestartPlcServerByClientName(_clientName);
                    //    if (!res.State)
                    //    {
                    //        LogHelper.WriteLog(LogType.Warn, $"通知PLC服务重启失败,失败原因: {res.Message}");
                    //    }
                    //}
                    LogHelper.WriteLog(LogType.Info, msg);
                    // 只处理一条连接,一个服务器.
                    await AcceptClientMsgAsync(tokenParent);
                }
            }
            catch (OperationCanceledException)
            {
                string msg = $"从站({_clientName}) 的监听任务被取消";
                LogHelper.WriteLog(LogType.Info, msg);
            }
            catch (Exception ex)
            {
                string msg = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
                if (msg.Contains("通常每个套接字地址(协议/网络地址/端口)只允许使用一次"))
                {
                    LogHelper.WriteLog(LogType.Info, $"端口{_clientPort}被占用,关闭对应进程!");
                    ProcessManager.KillProcessByPort(new List<string>() { $"192.168.1.20:{_clientPort}" });
                    return;
                }
                LogHelper.WriteLog(LogType.Exception, msg);
                return;
            }
            finally
            {
                _slaveState.ReadyStatus = false;
                if (TcpClientConnected != null)
                {
                    TcpClientConnected?.Dispose();
                    TcpClientConnected?.Close();
                    TcpClientConnected = null;
                }
                if (_listener != null)
                {
                    _listener.Stop();
                    _listener = null;
                }
                LogHelper.WriteLog(LogType.Info, $"从站({_clientName})服务器监听任务关闭!");
            }
        }

        /// <summary>
        /// 异步发送消息
        /// </summary>
        /// <returns></returns>
        public async Task SendMsgAsync(byte[] msgSend, bool isMainLog = false)
        {
            if (TcpClientConnected == null)
            {
                LogHelper.WriteLogSlave(LogType.Fatal, $"{msgSend} 发送失败,连接已经断开", _clientName);
            }
            NetworkStream? stream = TcpClientConnected?.GetStream();
            if (stream != null)
            {
                await stream.WriteAsync(msgSend, 0, msgSend.Length);
                if (isMainLog)
                {
                    LogHelper.WriteLog(LogType.Info, $"{Encoding.ASCII.GetString(msgSend).Replace("\r\n", "\\r\\n")} 消息发送成功!");
                }
                else
                {
                    LogHelper.WriteLogSlave(LogType.Info, $"{Encoding.ASCII.GetString(msgSend)} 消息发送成功!", _clientName);
                }
            }
        }

        /// <summary>
        /// 关闭服务器,关闭服务器的时候,是不是要先发送一条空消息呢,先看看直接关闭会怎么样.
        /// </summary>
        public void StopServerAsync()
        {
            ServerIsOpen = false;
            _tokenAsyncRead.Cancel();
            _tokenListener.Cancel();
            _slaveState.ReadyStatus = false;
            if (_listener != null)
            {
                _listener.Stop();
                _listener = null;
            }
            if (TcpClientConnected != null)
            {
                TcpClientConnected.Dispose();
                TcpClientConnected.Close();
                TcpClientConnected = null;
            }
            LogHelper.WriteLog(LogType.Info, $"主动结束从站({_clientName})的连接");
        }

        /// <summary>
        /// 处理接收消息的异步任务.
        /// </summary>
        /// <returns></returns>
        private async Task AcceptClientMsgAsync(CancellationTokenSource tokenParent)
        {
            try
            {
                using (NetworkStream stream = TcpClientConnected?.GetStream()!)
                {
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while (!tokenParent.IsCancellationRequested && ServerIsOpen)
                    {
                        bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, tokenParent.Token);
                        if (tokenParent.IsCancellationRequested || !ServerIsOpen)
                        {
                            stream.Close();
                            break;
                        }
                        if (bytesRead == 0)
                        {
                            _isAlive = false;
                            _slaveState.ConnectedStatus = "已断开";
                            stream.Close();
                            LogHelper.WriteLog(LogType.Warn, $"从站 {_clientName} 接收到数据长度为0,连接已断开,接收消息任务关闭!");
                            break;
                        }
                        string msgRec;
                        if (_clientName != "国产电阻率")
                        {
                            msgRec = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                        }
                        else
                        {
                            msgRec = Encoding.GetEncoding("GB2312").GetString(buffer, 0, bytesRead);
                            if (msgRec.Contains("温度值越界"))
                            {
                                continue; // 温度值越界消息不做处理.
                            }
                            msgRec = msgRec.Replace("\r\n", "\\r\\n");
                        }
                        LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到消息:  {msgRec}", _clientName);
                        // 测试的时候使用,测试TCP助手收发多少条数据
                        //TestTcpClientLog(_clientName!);
                        LastMsgTime = DateTime.Now; //更新最后一次获取消息的时间
                        Stopwatch sw = Stopwatch.StartNew();
                        DataResult parseMsgRes = ParseMsgFromSlave(msgRec);
                        sw.Stop();
                        string logInfo;
                        if (parseMsgRes.State)
                        {
                            logInfo = $"消息解析成功: 解析耗时: {sw.ElapsedMilliseconds} ms";
                            //LogHelper.WriteLog(LogType.Info, logInfo); 这条消息目前不打印,失败的时候才打印Log,成功的时候目前先不打印
                        }
                        else
                        {
                            logInfo = $"消息解析失败:{parseMsgRes.Message}, 解析耗时: {sw.ElapsedMilliseconds} ms";
                            LogHelper.WriteLogSlave(LogType.Info, logInfo, _clientName);
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                string msg = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
                LogHelper.WriteLog(LogType.Exception, msg);
                // 处理网络中断等异常情况
            }
            catch (Exception ex)
            {
                string msg = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
                LogHelper.WriteLog(LogType.Exception, msg);
                // 其他异常处理
            }
            finally
            {
                if (_isAlive)
                {
                    _isAlive = false;
                    _slaveState.ConnectedStatus = "已断开";
                    LogHelper.WriteLog(LogType.Info, $"从站 {_clientName} 接收消息任务关闭!");
                }
                if (TcpClientConnected != null)
                {
                    TcpClientConnected?.Dispose();
                    TcpClientConnected?.Close();
                    TcpClientConnected = null;
                }
            }
        }

        public static List<int> MsgCount = new List<int>() { 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        // 测试收发.尺寸,3D,前崩,后崩,左崩,右崩,上脏污,下脏污,隐裂
        private void TestTcpClientLog(string clientName)
        {
            if (clientName == "尺寸")
            {
                MsgCount[0] += 1;
            }
            if (clientName == "3D")
            {
                MsgCount[1] += 1;
            }
            if (clientName == "前崩")
            {
                MsgCount[2] += 1;
            }
            if (clientName == "后崩")
            {
                MsgCount[3] += 1;
            }
            if (clientName == "左崩")
            {
                MsgCount[4] += 1;
            }
            if (clientName == "右崩")
            {
                MsgCount[5] += 1;
            }
            if (clientName == "上脏污")
            {
                MsgCount[6] += 1;
            }
            if (clientName == "下脏污")
            {
                MsgCount[7] += 1;
            }
            if (clientName == "隐裂")
            {
                MsgCount[8] += 1;
            }
            LogHelper.WriteLog(LogType.Info, $"消息统计: 尺寸({MsgCount[0]}),3D({MsgCount[1]})," +
                $"前崩({MsgCount[2]}),后崩({MsgCount[3]}),左崩({MsgCount[4]}),右崩({MsgCount[5]}),上脏污({MsgCount[6]}),下脏污({MsgCount[7]}),隐裂({MsgCount[8]})");
        }


        /// <summary>
        /// 解析从站的消息.
        /// </summary>
        /// <param name="msgRec"></param>
        /// <returns></returns>
        private DataResult ParseMsgFromSlave(string msgRec)
        {
            DataResult result = new DataResult();
            result.State = true;
            if (_clientName == "国产电阻率")
            {
                DataResult<List<string>> dataResult = new DataResult<List<string>>();
                if (GlobalValues.ResistivityDataGetMode == 0)
                {
                    dataResult = MsgParseHelper.ParseResistivityDataSimple(msgRec);
                    if (!dataResult.State)
                    {
                        // 电阻率获取失败
                        //LogHelper.WriteLog(LogType.Fatal, dataResult.Message);
                    }
                    else
                    {
                        // 数据获取成功.
                        List<string> data = dataResult.Data!;
                        // 根据这个数据去计算其等级.
                        //CalcDetectedLevel.CalcResistivityLevel(data);
                        if (GlobalValues.NaponsResistivityQueue.Count > 0)
                        {
                            string[] naponsVal = GlobalValues.NaponsResistivityQueue.Dequeue();
                            // 将数据data乘以K和B
                            double thickness = double.Parse(naponsVal[1]);
                            data[0] = (GlobalValues.ResistivityK * thickness * 0.0001 * (double.Parse(data[0])) + GlobalValues.ResistivityB).ToString(); // 电阻率
                            data[1] = (GlobalValues.ResistivityK * thickness * 0.0001 * (double.Parse(data[1])) + GlobalValues.ResistivityB).ToString(); // 最大值
                            data[2] = (GlobalValues.ResistivityK * thickness * 0.0001 * (double.Parse(data[2])) + GlobalValues.ResistivityB).ToString(); // 最小值

                            List<string> newVal = naponsVal.Concat(data).ToList();
                            CsvHelper.WriteToCsvSingleLine(GlobalValues.ResistivityDataPath, newVal);
                        }
                        else
                        {
                            LogHelper.WriteLog(LogType.Fatal, "国产电阻率数据出错,没有收到Napons电阻率相关信息");
                        }

                    }
                }
                else if (GlobalValues.ResistivityDataGetMode == 1)
                {
                    dataResult = MsgParseHelper.ParseResistivityDataNotCombine(msgRec);
                }
                else
                {
                    dataResult = MsgParseHelper.ParseResistivityDataDetail(msgRec);
                }
            }
            else if (_clientName == "尺寸")
            {
                // 先解析消息分包,后面一个参数表示移除掉空白项
                string[] subMsg = msgRec.Split(new[] { "End" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in subMsg)
                {
                    string singleMsg = s.TrimEnd() + "End";
                    DataResult<List<string>> msgResPc1 = MsgParseHelper.ParseSizeDataFromPc1(singleMsg);
                    if (msgResPc1.State)
                    {
                        List<string> msgDataPc1 = msgResPc1.Data!;
                        // 先获取到对应的共同的内容 [流水号,Pc名称,相机编号]
                        string waferId = msgDataPc1[0];
                        string pcName = msgDataPc1[1];
                        string cameraNum = msgDataPc1[2];
                        if (msgDataPc1.Count == 4)
                        {
                            // 收到错误消息,先获取错误码
                            string errorCode = msgDataPc1[3];
                            if (errorCode.Equals("ClearOK", StringComparison.OrdinalIgnoreCase))
                            {
                                // 接收到了清空消息回复
                                ClearResponseIsOk = true;
                                LogHelper.WriteLog(LogType.Info, $"{_clientName} 收到清空队列信号回复!");
                            }
                            else
                            {
                                // 发送消息给视觉PC消息.
                                _ = SendMsgAsync(MsgPackHelper.GetErrorCodeResponseMsgSend(pcName, cameraNum, waferId, errorCode), true);
                                LogHelper.WriteLog(LogType.Info, $"{_clientName}工位收到视觉拍照错误状况,错误码为: {errorCode},错误描述: {MsgErrorHelperPc.GetErrorInfoByCode(errorCode)},对应流水号:{waferId}");
                                // 将解析的等级写入到(物料号等级字典)中去.
                                // 如果没有屏蔽这个工位再写入
                                if (!GlobalValues.ModuleIsShield.Contains(_clientName))
                                {
                                    WriteErrorLevelToWaferLevel(waferId, errorCode);
                                }
                            }
                        }
                        else
                        {
                            // 收到正确的消息,尺寸工位的消息处理.
                            WriteNormalLevelToWaferLevel(waferId, pcName, cameraNum, msgDataPc1.Skip(3).Take(msgDataPc1.Count - 3).ToList());
                            _ = SendMsgAsync(MsgPackHelper.GetOkResponseMsgSend(pcName, cameraNum, waferId));
                        }
                        // 将这条数据保存到流水号和消息字典中去,然后去判断数据是否完整,如果数据完整就将数据写入到料盒中去.
                        KeepMsgRecvFromWhere(waferId, pcName);
                    }
                    else
                    {

                    }
                }
            }
            else if (_clientName!.Contains("崩边隐裂") && (!msgRec.Contains("Subfi")))
            {
                // 先解析消息分包,后面一个参数表示移除掉空白项
                string[] subMsg = msgRec.Split(new[] { "End" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in subMsg)
                {
                    string singleMsg = s.TrimEnd() + "End";
                    DataResult<List<string>> msgResPc1 = MsgParseHelper.ParseEdgeBreakFromPc2(singleMsg);
                    if (msgResPc1.State)
                    {
                        List<string> msgDataPc1 = msgResPc1.Data!;
                        // 先获取到对应的共同的内容 [流水号,Pc名称,相机编号]
                        string waferId = msgDataPc1[0];
                        string pcName = msgDataPc1[1];
                        string cameraNum = msgDataPc1[2];
                        KeepMsgRecvFromWhere(waferId, pcName);
                        if (msgDataPc1.Count == 4)
                        {
                            // 收到错误消息,先获取错误码
                            string errorCode = msgDataPc1[3];
                            if (errorCode.Equals("ClearOK", StringComparison.OrdinalIgnoreCase))
                            {
                                // 接收到了清空消息回复
                                ClearResponseIsOk = true;
                                LogHelper.WriteLog(LogType.Info, $"{_clientName} 收到清空队列信号回复!");
                            }
                            else
                            {
                                // 发送消息给PC
                                _ = SendMsgAsync(MsgPackHelper.GetErrorCodeResponseMsgSend(pcName, cameraNum, waferId, errorCode));
                                LogHelper.WriteLogSlave(LogType.Info, $"{_clientName}工位收到视觉拍照错误状况,错误码为: {errorCode},错误描述: {MsgErrorHelperPc.GetErrorInfoByCode(errorCode)}", _clientName);
                                if (!GlobalValues.ModuleIsShield.Contains(_clientName))
                                {
                                    // 将解析的等级写入到(物料号等级字典)中去.
                                    WriteErrorLevelToWaferLevel(waferId, errorCode);
                                }
                            }
                        }
                        else
                        {
                            // 收到正确的消息,尺寸工位的消息处理.
                            WriteNormalLevelToWaferLevel(waferId, pcName, cameraNum, msgDataPc1.Skip(3).Take(msgDataPc1.Count - 3).ToList());
                            _ = SendMsgAsync(MsgPackHelper.GetOkResponseMsgSend(pcName, cameraNum, waferId));
                        }
                    }
                    else
                    {

                    }
                }
            }
            else if (_clientName == "3D")
            {
                // 先解析消息分包,后面一个参数表示移除掉空白项
                string[] subMsg = msgRec.Split(new[] { "End" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in subMsg)
                {
                    string singleMsg = s.TrimEnd() + "End";
                    DataResult<List<string>> msgResPc1 = MsgParseHelper.ParseThickness3DFromPc3(singleMsg);
                    if (msgResPc1.State)
                    {
                        List<string> msgDataPc1 = msgResPc1.Data!;
                        // 先获取到对应的共同的内容 [流水号,Pc名称,相机编号]
                        string waferId = msgDataPc1[0];
                        string pcName = msgDataPc1[1];
                        string cameraNum = msgDataPc1[2];
                        if (msgDataPc1.Count == 4)
                        {
                            // 收到错误消息,先获取错误码
                            string errorCode = msgDataPc1[3];
                            if (errorCode.Equals("ClearOK", StringComparison.OrdinalIgnoreCase))
                            {
                                // 接收到了清空消息回复
                                ClearResponseIsOk = true;
                                LogHelper.WriteLog(LogType.Info, $"{_clientName} 收到清空队列信号回复!");
                            }
                            else if (errorCode.Equals("CorrectOK", StringComparison.OrdinalIgnoreCase))
                            {
                                // 标定OK的处理.
                                Calibration3DIsOK = true;
                            }
                            else if (errorCode.Equals("CorrectNG", StringComparison.OrdinalIgnoreCase))
                            {
                                // 标定OK的处理.
                                Calibration3DIsOK = false;
                                Calibration3DErrorInfo = "3D相机标定,视觉返回结果NG";
                            }
                            else if (errorCode.Equals("CorrectWarn", StringComparison.OrdinalIgnoreCase))
                            {
                                // 标定OK的处理.
                                Calibration3DIsOK = false;
                                Calibration3DErrorInfo = "3D相机标定,视觉返回结果,控制器异常、立刻停机，排查控制器异常";
                            }
                            else
                            {
                                // 发送消息给PC
                                _ = SendMsgAsync(MsgPackHelper.GetErrorCodeResponseMsgSend(pcName, cameraNum, waferId, errorCode));
                                if (!GlobalValues.ModuleIsShield.Contains(_clientName))
                                {
                                    // 将解析的等级写入到(物料号等级字典)中去.
                                    WriteErrorLevelToWaferLevel(waferId, errorCode);
                                }
                                LogHelper.WriteLog(LogType.Info, $"{_clientName}工位收到视觉拍照错误状况,错误码为: {errorCode},错误描述: {MsgErrorHelperPc.GetErrorInfoByCode(errorCode)}");
                            }
                        }
                        else
                        {
                            _ = SendMsgAsync(MsgPackHelper.GetOkResponseMsgSend(pcName, cameraNum, waferId));
                            // 收到正确的消息,尺寸工位的消息处理.
                            WriteNormalLevelToWaferLevel(waferId, pcName, cameraNum, msgDataPc1.Skip(3).Take(msgDataPc1.Count - 3).ToList());
                        }
                        KeepMsgRecvFromWhere(waferId, pcName);
                    }
                    else
                    {

                    }
                }
            }
            else if (_clientName!.Contains("脏污"))
            {
                // 先解析消息分包,后面一个参数表示移除掉空白项
                string[] subMsg = msgRec.Split(new[] { "End" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in subMsg)
                {
                    string singleMsg = s.TrimEnd() + "End";
                    DataResult<List<string>> msgResPc1 = MsgParseHelper.ParseSmudgeDataFromPc4(singleMsg);
                    if (msgResPc1.State)
                    {
                        List<string> msgDataPc1 = msgResPc1.Data!;
                        // 先获取到对应的共同的内容 [流水号,Pc名称,相机编号]
                        string waferId = msgDataPc1[0];
                        string pcName = msgDataPc1[1];
                        string cameraNum = msgDataPc1[2];
                        if (msgDataPc1.Count == 4)
                        {
                            // 收到错误消息,先获取错误码
                            // 发送消息给PC
                            string errorCode = msgDataPc1[3];
                            if (errorCode.Equals("ClearOK", StringComparison.OrdinalIgnoreCase))
                            {
                                // 接收到了清空消息回复
                                ClearResponseIsOk = true;
                                LogHelper.WriteLog(LogType.Info, $"{_clientName} 收到清空队列信号回复!");
                            }
                            else
                            {
                                _ = SendMsgAsync(MsgPackHelper.GetErrorCodeResponseMsgSend(pcName, cameraNum, waferId, errorCode));
                                LogHelper.WriteLog(LogType.Info, $"{_clientName}工位收到视觉拍照错误状况,错误码为: {errorCode},错误描述: {MsgErrorHelperPc.GetErrorInfoByCode(errorCode)}");
                                if (!GlobalValues.ModuleIsShield.Contains(_clientName))
                                {
                                    // 将解析的等级写入到(物料号等级字典)中去.
                                    WriteErrorLevelToWaferLevel(waferId, errorCode);
                                }
                            }
                        }
                        else
                        {
                            _ = SendMsgAsync(MsgPackHelper.GetOkResponseMsgSend(pcName, cameraNum, waferId));
                            // 收到正确的消息,尺寸工位的消息处理.
                            WriteNormalLevelToWaferLevel(waferId, pcName, cameraNum, msgDataPc1.Skip(3).Take(msgDataPc1.Count - 3).ToList());
                        }
                        KeepMsgRecvFromWhere(waferId, pcName);
                    }
                    else
                    {

                    }
                }
            }
            else if (_clientName == "崩边隐裂" && (msgRec.Contains("Subfi")))
            {
                // 先解析消息分包,后面一个参数表示移除掉空白项
                string[] subMsg = msgRec.Split(new[] { "End" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in subMsg)
                {
                    string singleMsg = s.TrimEnd() + "End";
                    DataResult<List<string>> msgResPc1 = MsgParseHelper.ParseSubfissureDataFromPc5(singleMsg);
                    if (msgResPc1.State)
                    {
                        List<string> msgDataPc1 = msgResPc1.Data!;
                        // 先获取到对应的共同的内容 [流水号,Pc名称,相机编号]
                        string waferId = msgDataPc1[0];
                        string pcName = msgDataPc1[1];
                        string cameraNum = msgDataPc1[2];
                        if (msgDataPc1.Count == 4)
                        {
                            // 发送消息给PC
                            string errorCode = msgDataPc1[3];
                            if (errorCode.Equals("ClearOK", StringComparison.OrdinalIgnoreCase))
                            {
                                // 接收到了清空消息回复
                                ClearResponseIsOk = true;
                                LogHelper.WriteLog(LogType.Info, $"{_clientName} 收到清空队列信号回复!");
                            }
                            else
                            {
                                _ = SendMsgAsync(MsgPackHelper.GetErrorCodeResponseMsgSend(pcName, cameraNum, waferId, errorCode));
                                // 收到错误消息,先获取错误码
                                LogHelper.WriteLogSlave(LogType.Info, $"{_clientName}工位收到视觉拍照错误状况,错误码为: {errorCode},错误描述: {MsgErrorHelperPc.GetErrorInfoByCode(errorCode)}", _clientName);
                                if (!GlobalValues.ModuleIsShield.Contains(_clientName))
                                {
                                    // 将解析的等级写入到(物料号等级字典)中去.
                                    WriteErrorLevelToWaferLevel(waferId, errorCode);
                                }
                            }
                        }
                        else
                        {
                            _ = SendMsgAsync(MsgPackHelper.GetOkResponseMsgSend(pcName, cameraNum, waferId));
                            // 收到正确的消息,尺寸工位的消息处理.
                            WriteNormalLevelToWaferLevel(waferId, pcName, cameraNum, msgDataPc1.Skip(3).Take(msgDataPc1.Count - 3).ToList());
                        }
                        KeepMsgRecvFromWhere(waferId, pcName);
                    }
                    else
                    {

                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 根据接收到的消息的上位机名称和相机编号,来保存对应的消息.
        /// 主要是用来最后分选的时候,看看是否6个工位都接收到了消息.
        /// </summary>
        /// <param name="pcName"></param>
        /// <param name="cameraNum"></param>
        private void KeepMsgRecvFromWhere(string waferId, string pcName)
        {
            List<string> listVal = new List<string>();
            if (GlobalValues.WaferIdFromPcDictionary.ContainsKey(waferId))
            {
                listVal = GlobalValues.WaferIdFromPcDictionary[waferId];
                listVal.Add(pcName);
            }
            else
            {
                listVal.Add(pcName);
            }
            GlobalValues.WaferIdFromPcDictionary[waferId] = listVal;
        }


        /// <summary>
        /// 将消息写入到字典等级中去,具体其对应的等级
        /// </summary>
        /// <param name="waferId"></param>
        /// <param name="pcName"></param>
        /// <param name="cameraNum"></param>
        /// <param name="msgContent"></param>
        private void WriteNormalLevelToWaferLevel(string waferId, string pcName, string cameraNum, List<string> msgContent)
        {
            Dictionary<string, List<int>> levelMap = new Dictionary<string, List<int>>();
            // 如果已经存在了,就不用赋值了.
            if (GlobalValues.WaferIdLevelDictionary.ContainsKey(waferId))
            {
                levelMap = GlobalValues.WaferIdLevelDictionary[waferId];
            }
            else
            {
                GlobalValues.WaferIdLevelDictionary[waferId] = levelMap;
            }
            try
            {
                string logInfo = "";
                if (pcName == "Size")
                {
                    //updateFields.Add("DetectedTime");
                    //updateVals.Add(DateTimeHelper.GetTimeNowForSql());
                    //// 尺寸工位,将生产日期添加上去
                    //updateFields.Add("ProductionDate");
                    //updateVals.Add(DateTimeHelper.GetProductionDatetime());

                    // 创建尺寸工位的数据保存容器
                    string[] sizeDataArray = new string[GlobalValues.SizeTitle.Length];

                    // X边长最大值 0
                    string? lengthXMax = FloatCalcHelper.SizeAddOffset(msgContent[22], GlobalValues.VisionOffsetMap["LengthYMax"]);
                    List<int> lengthXMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthXMaxRule, lengthXMax);
                    sizeDataArray[0] = CsvHelper.GetNumberValForCsv(lengthXMax);

                    // X边长最小值 1
                    string? lengthXMin = FloatCalcHelper.SizeAddOffset(msgContent[23], GlobalValues.VisionOffsetMap["LengthXMin"]);
                    List<int> lengthXMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthXMinRule, lengthXMin);
                    sizeDataArray[1] = CsvHelper.GetNumberValForCsv(lengthXMin);


                    // Y边长最大值 2
                    string? lengthYMax = FloatCalcHelper.SizeAddOffset(msgContent[24], GlobalValues.VisionOffsetMap["LengthYMax"]);
                    List<int> lengthYMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthYMaxRule, lengthYMax);
                    sizeDataArray[2] = CsvHelper.GetNumberValForCsv(lengthYMax);


                    // Y边长最小值 3
                    string? lengthYMin = FloatCalcHelper.SizeAddOffset(msgContent[25], GlobalValues.VisionOffsetMap["LengthYMin"]);
                    List<int> lengthYMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthYMinRule, lengthYMin);
                    sizeDataArray[3] = CsvHelper.GetNumberValForCsv(lengthYMin);


                    // 边长最大值 4
                    string lengthMax = FloatCalcHelper.SizeAddOffset(msgContent[0], GlobalValues.VisionOffsetMap["LengthMax"]);
                    // 获取对应的等级根据这个值去过去对应等级.
                    List<int> lengthMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthMaxRule, lengthMax);
                    sizeDataArray[4] = CsvHelper.GetNumberValForCsv(lengthMax);



                    // 边长最小值 5
                    string lengthMin = FloatCalcHelper.SizeAddOffset(msgContent[1], GlobalValues.VisionOffsetMap["LengthYMax"]);
                    List<int> lengthMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthMinRule, lengthMin);
                    sizeDataArray[5] = CsvHelper.GetNumberValForCsv(lengthMin);


                    // X边长 6
                    string lengthX = FloatCalcHelper.SizeAddOffset(msgContent[2], GlobalValues.VisionOffsetMap["LengthX"]);
                    List<int> lengthXLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthXRule, lengthX);
                    sizeDataArray[6] = CsvHelper.GetNumberValForCsv(lengthX);


                    // Y边长 7
                    string? lengthY = FloatCalcHelper.SizeAddOffset(msgContent[3], GlobalValues.VisionOffsetMap["LengthY"]);
                    List<int> lengthYLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LengthYRule, lengthY);
                    sizeDataArray[7] = CsvHelper.GetNumberValForCsv(lengthY);


                    // 对角线左上右下 8
                    string? diagonalLeftStart = FloatCalcHelper.SizeAddOffset(msgContent[4], GlobalValues.VisionOffsetMap["DiagonalLeftStart"]);
                    List<int> diagonalLeftStartLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.DiagonalLeftStartRule, diagonalLeftStart);
                    sizeDataArray[8] = CsvHelper.GetNumberValForCsv(diagonalLeftStart);


                    // 对角线左下右上 9
                    string? dialonalRightStart = FloatCalcHelper.SizeAddOffset(msgContent[5], GlobalValues.VisionOffsetMap["DialonalRightStart"]);
                    List<int> dialonalRightStartLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.DialonalRightStartRule, dialonalRightStart);
                    sizeDataArray[9] = CsvHelper.GetNumberValForCsv(dialonalRightStart);


                    // 倒角最大值 7
                    string? chamferMax = FloatCalcHelper.SizeAddOffset(msgContent[6], GlobalValues.VisionOffsetMap["ChamferMax"]);
                    List<int> chamferMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ChamferMaxRule, chamferMax);
                    sizeDataArray[10] = CsvHelper.GetNumberValForCsv(chamferMax);


                    // 倒角最小值 8
                    string? chamferMin = FloatCalcHelper.SizeAddOffset(msgContent[7], GlobalValues.VisionOffsetMap["ChamferMin"]);
                    List<int> chamferMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ChamferMinRule, chamferMin);
                    sizeDataArray[11] = CsvHelper.GetNumberValForCsv(chamferMin);


                    // 上下平行度 9
                    string? upDownParallel = FloatCalcHelper.SizeAddOffset(msgContent[8], GlobalValues.VisionOffsetMap["UpDownParallel"]);
                    List<int> upDownParallelLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.UpDownParallelRule, upDownParallel);
                    sizeDataArray[12] = CsvHelper.GetNumberValForCsv(upDownParallel);


                    // 左右平行度 10
                    string? leftRightParallel = FloatCalcHelper.SizeAddOffset(msgContent[9], GlobalValues.VisionOffsetMap["LeftRightParallel"]);
                    List<int> leftRightParallelLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftRightParallelRule, leftRightParallel);
                    sizeDataArray[13] = CsvHelper.GetNumberValForCsv(leftRightParallel);


                    // 直角边最大值 11
                    string? squareLineMax = FloatCalcHelper.SizeAddOffset(msgContent[10], GlobalValues.VisionOffsetMap["SquareLineMax"]);
                    List<int> squareLineMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SquareLineMaxRule, squareLineMax);
                    sizeDataArray[14] = CsvHelper.GetNumberValForCsv(squareLineMax);


                    // 直角边最小值 12
                    string? squareLineMin = FloatCalcHelper.SizeAddOffset(msgContent[11], GlobalValues.VisionOffsetMap["SquareLineMin"]);
                    List<int> squareLineMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SquareLineMinRule, squareLineMin);
                    sizeDataArray[15] = CsvHelper.GetNumberValForCsv(squareLineMin);


                    // 垂直度最大值 13
                    string? verticalAngleMax = FloatCalcHelper.SizeAddOffset(msgContent[12], GlobalValues.VisionOffsetMap["VerticalAngleMax"]);
                    List<int> verticalAngleMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.VerticalAngleMaxRule, verticalAngleMax);
                    sizeDataArray[16] = CsvHelper.GetNumberValForCsv(verticalAngleMax);


                    // 垂直度最小值 14
                    string? verticalAngleMin = FloatCalcHelper.SizeAddOffset(msgContent[13], GlobalValues.VisionOffsetMap["VerticalAngleMin"]);
                    List<int> verticalAngleMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.VerticalAngleMinRule, verticalAngleMin);
                    sizeDataArray[17] = CsvHelper.GetNumberValForCsv(verticalAngleMin);


                    // 左上倒角 15
                    string? leftTopCharmfer = FloatCalcHelper.SizeAddOffset(msgContent[14], GlobalValues.VisionOffsetMap["LeftTopCharmfer"]);
                    List<int> leftTopCharmferLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftTopCharmferRule, leftTopCharmfer);
                    sizeDataArray[18] = CsvHelper.GetNumberValForCsv(leftTopCharmfer);


                    // 右上倒角 16
                    string? rightTopCharmfer = FloatCalcHelper.SizeAddOffset(msgContent[15], GlobalValues.VisionOffsetMap["RightTopCharmfer"]);
                    List<int> rightTopCharmferLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightTopCharmferRule, rightTopCharmfer);
                    sizeDataArray[19] = CsvHelper.GetNumberValForCsv(rightTopCharmfer);


                    // 左下倒角 17
                    string? leftBottomCharmfer = FloatCalcHelper.SizeAddOffset(msgContent[16], GlobalValues.VisionOffsetMap["LeftBottomCharmfer"]);
                    List<int> leftBottomCharmferLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftBottomCharmferRule, leftBottomCharmfer);
                    sizeDataArray[20] = CsvHelper.GetNumberValForCsv(leftBottomCharmfer);


                    // 右下倒角 18
                    string? rightBottomCharmfer = FloatCalcHelper.SizeAddOffset(msgContent[17], GlobalValues.VisionOffsetMap["RightBottomCharmfer"]);
                    List<int> rightBottomCharmferLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightBottomCharmferRule, rightBottomCharmfer);
                    sizeDataArray[21] = CsvHelper.GetNumberValForCsv(rightBottomCharmfer);


                    // 左上角度 19
                    string? leftTopAngle = FloatCalcHelper.SizeAddOffset(msgContent[18], GlobalValues.VisionOffsetMap["LeftTopAngle"]);
                    List<int> leftTopAngleLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftTopAngleRule, leftTopAngle);
                    sizeDataArray[22] = CsvHelper.GetNumberValForCsv(leftTopAngle);



                    // 右上角度 20
                    string? rightTopAngle = FloatCalcHelper.SizeAddOffset(msgContent[19], GlobalValues.VisionOffsetMap["RightTopAngle"]);
                    List<int> rightTopAngleLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightTopAngleRule, rightTopAngle);
                    sizeDataArray[23] = CsvHelper.GetNumberValForCsv(rightTopAngle);


                    // 左下角度 21
                    string? leftBottomAngle = FloatCalcHelper.SizeAddOffset(msgContent[20], GlobalValues.VisionOffsetMap["LeftBottomAngle"]);
                    List<int> leftBottomAngleLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftBottomAngleRule, leftBottomAngle);
                    sizeDataArray[24] = CsvHelper.GetNumberValForCsv(leftBottomAngle);


                    // 右下角度 22
                    string? rightBottomAngle = FloatCalcHelper.SizeAddOffset(msgContent[21], GlobalValues.VisionOffsetMap["RightBottomAngle"]);
                    List<int> rightBottomAngleLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightBottomAngleRule, rightBottomAngle);
                    sizeDataArray[25] = CsvHelper.GetNumberValForCsv(rightBottomAngle);

                    GlobalValues.WaferDataSize[waferId] = sizeDataArray; // 将数据保存到全局变量中


                    if (!GlobalValues.ModuleIsShield.Contains("尺寸"))
                    {
                        if (lengthMaxLevel.Count > 0)
                        {
                            levelMap["data01"] = lengthMaxLevel;
                        }
                        if (lengthMinLevel.Count > 0)
                        {
                            levelMap["data02"] = lengthMinLevel;
                        }
                        if (lengthXLevel.Count > 0)
                        {
                            levelMap["data03"] = lengthXLevel;
                        }
                        if (lengthYLevel.Count > 0)
                        {
                            levelMap["data04"] = lengthYLevel;
                        }
                        if (diagonalLeftStartLevel.Count > 0)
                        {
                            levelMap["data05"] = diagonalLeftStartLevel;
                        }
                        if (dialonalRightStartLevel.Count > 0)
                        {
                            levelMap["data06"] = dialonalRightStartLevel;
                        }
                        if (chamferMaxLevel.Count > 0)
                        {
                            levelMap["data07"] = chamferMaxLevel;
                        }
                        if (chamferMinLevel.Count > 0)
                        {
                            levelMap["data08"] = chamferMinLevel;
                        }
                        if (upDownParallelLevel.Count > 0)
                        {
                            levelMap["data09"] = upDownParallelLevel;
                        }
                        if (leftRightParallelLevel.Count > 0)
                        {
                            levelMap["data10"] = leftRightParallelLevel;
                        }
                        if (squareLineMaxLevel.Count > 0)
                        {
                            levelMap["data11"] = squareLineMaxLevel;
                        }
                        if (squareLineMinLevel.Count > 0)
                        {
                            levelMap["data12"] = squareLineMinLevel;
                        }
                        if (verticalAngleMaxLevel.Count > 0)
                        {
                            levelMap["data13"] = verticalAngleMaxLevel;
                        }
                        if (verticalAngleMinLevel.Count > 0)
                        {
                            levelMap["data14"] = verticalAngleMinLevel;
                        }
                        if (leftTopCharmferLevel.Count > 0)
                        {
                            levelMap["data15"] = leftTopCharmferLevel;
                        }
                        if (rightTopCharmferLevel.Count > 0)
                        {
                            levelMap["data16"] = rightTopCharmferLevel;
                        }
                        if (leftBottomCharmferLevel.Count > 0)
                        {
                            levelMap["data17"] = leftBottomCharmferLevel;
                        }
                        if (rightBottomCharmferLevel.Count > 0)
                        {
                            levelMap["data18"] = rightBottomCharmferLevel;
                        }
                        if (leftTopAngleLevel.Count > 0)
                        {
                            levelMap["data19"] = leftTopAngleLevel;
                        }
                        if (rightTopAngleLevel.Count > 0)
                        {
                            levelMap["data20"] = rightTopAngleLevel;
                        }
                        if (leftBottomAngleLevel.Count > 0)
                        {
                            levelMap["data21"] = leftBottomAngleLevel;
                        }
                        if (lengthXMaxLevel.Count > 0)
                        {
                            levelMap["data23"] = lengthXMaxLevel;
                        }
                        if (lengthXMaxLevel.Count > 0)
                        {
                            levelMap["data24"] = lengthXMaxLevel;
                        }
                        if (lengthYMaxLevel.Count > 0)
                        {
                            levelMap["data25"] = lengthYMaxLevel;
                        }
                        if (lengthYMinLevel.Count > 0)
                        {
                            levelMap["data26"] = lengthYMinLevel;
                        }

                    }
                    logInfo = $"{_clientName} 解析消息内容: 边长最大值(Lv):{lengthMax}({lengthMaxLevel.ToString<int>()}),边长最小值(Lv):{lengthMin}({lengthMinLevel.ToString<int>()})," +
                        $"X边长(Lv):{lengthX}({lengthXLevel.ToString<int>()}), Y边长(Lv):{lengthY}({lengthYLevel.ToString<int>()}),对角线左上右下(Lv):{diagonalLeftStart}({diagonalLeftStartLevel.ToString<int>()})\n" +
                        $"对角线左下右上(Lv):{dialonalRightStart}({dialonalRightStartLevel.ToString<int>()}),倒角最大值(Lv):{chamferMax}({chamferMaxLevel.ToString<int>()}),倒角最小值(Lv):{chamferMin}({chamferMinLevel.ToString<int>()})" +
                        $"上下平行度(Lv):{upDownParallel}({upDownParallelLevel.ToString<int>()}),左右平行度(Lv):{leftRightParallel}({leftRightParallelLevel.ToString<int>()}),直角边最大值(Lv):{squareLineMax}({squareLineMaxLevel.ToString<int>()})," +
                        $"直角边最小值(Lv):{squareLineMin}({squareLineMinLevel.ToString<int>()}), 垂直度最大值(Lv):{verticalAngleMax}({verticalAngleMaxLevel.ToString<int>()})\n垂直度最小值(Lv):{verticalAngleMin}({verticalAngleMinLevel.ToString<int>()})," +
                        $"左上倒角边长(Lv):{leftTopCharmfer}({leftTopCharmferLevel.ToString<int>()}),右上倒角边长(Lv):{rightTopCharmfer}({rightTopCharmferLevel.ToString<int>()}),左下倒角边长(Lv):{leftBottomCharmfer}({leftBottomCharmferLevel.ToString<int>()})" +
                        $"右下倒角边长(Lv):{rightBottomCharmfer}({rightBottomCharmferLevel.ToString<int>()}),左上角度(Lv):{leftTopAngle}({leftTopAngleLevel.ToString<int>()}),右上角度(Lv):{rightTopAngle}({rightTopAngleLevel.ToString<int>()})," +
                        $"左下角度(Lv):{leftBottomAngle}({leftBottomAngleLevel.ToString<int>()}),右下角度(Lv):{rightBottomAngle}({rightBottomAngleLevel.ToString<int>()},X边长最大值(Lv):{lengthXMax}({lengthXMaxLevel.ToString<int>()}," +
                        $"X边长最小值(Lv):{lengthXMin}({lengthXMinLevel.ToString<int>()},Y边长最大值(Lv):{lengthYMax}({lengthYMaxLevel.ToString<int>()},Y边长最小值(Lv):{lengthYMin}({lengthYMinLevel.ToString<int>()})";
                }

                else if (pcName == "ThreeD")
                {
                    string[] Data3D01 = new string[GlobalValues.Title3D01.Length];
                    string[] Data3D02 = new string[GlobalValues.Title3D02.Length];

                    // 平均厚度 1
                    string? thicknessAver = FloatCalcHelper.SizeAddOffset(msgContent[0], GlobalValues.VisionOffsetMap["ThicknessAver"]);
                    // 去保存电阻率的值
                    CalcAndKeepResistivityWithThickness(waferId, Convert.ToDouble(thicknessAver));
                    //GlobalValues.ThicknessMap[waferId] = Convert.ToDouble(thicknessAver); // 将厚度按照流水号保存到全局变量中去
                    List<int> thicknessAverLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ThicknessAverRule, thicknessAver);
                    Data3D01[0] = CsvHelper.GetNumberValForCsv(thicknessAver);

                    // TTV 2
                    string? TTV = FloatCalcHelper.SizeAddOffset(msgContent[1], GlobalValues.VisionOffsetMap["TTV"]);
                    List<int> TTVLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.TTVRule, TTV);
                    Data3D01[1] = CsvHelper.GetNumberValForCsv(TTV);

                    // 线痕最大值 3
                    string? lineTraceMax = FloatCalcHelper.SizeAddOffset(msgContent[2], GlobalValues.VisionOffsetMap["LineTraceMax"]);
                    List<int> lineTraceMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LineTraceMaxRule, lineTraceMax);
                    Data3D01[2] = CsvHelper.GetNumberValForCsv(lineTraceMax);


                    // 翘曲 4
                    string? warping = FloatCalcHelper.SizeAddOffset(msgContent[3], GlobalValues.VisionOffsetMap["Warping"]);
                    List<int> warpingLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.WarpingRule, warping);
                    Data3D01[3] = CsvHelper.GetNumberValForCsv(warping);


                    // 最小厚度 5
                    string? thicknessMin = FloatCalcHelper.SizeAddOffset(msgContent[4], GlobalValues.VisionOffsetMap["ThicknessMin"]);
                    List<int> thicknessMinLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ThicknessMinRule, thicknessMin);
                    Data3D02[0] = CsvHelper.GetNumberValForCsv(thicknessMin);

                    // 最大厚度 6
                    string? thicknessMax = FloatCalcHelper.SizeAddOffset(msgContent[5], GlobalValues.VisionOffsetMap["ThicknessMax"]);
                    List<int> thicknessMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ThicknessMaxRule, thicknessMax);
                    Data3D02[1] = CsvHelper.GetNumberValForCsv(thicknessMax);


                    // 是否密集线痕 7
                    string? isDenseLine = msgContent[6];
                    List<int> isDenseLineLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.IsDenseLineRule, isDenseLine);
                    Data3D02[2] = isDenseLine.Equals("1") ? "是" : "否";


                    // 上线痕数量 8
                    //string? lineTraceUpNum = FloatCalcHelper.SizeAddOffset(msgContent[7], GlobalValues.VisionOffsetMap["LineTraceUpNum"]);
                    string? lineTraceUpNum = msgContent[7]; // 数量不补偿
                    List<int> lineTraceUpNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LineTraceUpNumRule, lineTraceUpNum);
                    Data3D02[3] = CsvHelper.GetNumberValForCsv(lineTraceUpNum);


                    // 上线痕数量最大值 9
                    //string? lineTraceUpMax = FloatCalcHelper.SizeAddOffset(msgContent[8], GlobalValues.VisionOffsetMap["LineTraceUpMax"]);
                    string? lineTraceUpMax = msgContent[8];
                    List<int> lineTraceUpMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LineTraceUpMaxRule, lineTraceUpMax);
                    Data3D02[4] = CsvHelper.GetNumberValForCsv(lineTraceUpMax);


                    // 下线痕数量 10
                    //string? lineTraceDownNum = FloatCalcHelper.SizeAddOffset(msgContent[9], GlobalValues.VisionOffsetMap["LineTraceDownNum"]);
                    string? lineTraceDownNum = msgContent[9];
                    List<int> lineTraceDownNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LineTraceDownNumRule, lineTraceDownNum);
                    Data3D02[5] = CsvHelper.GetNumberValForCsv(lineTraceDownNum);


                    // 下线痕数量最大值 11
                    //string? lineTraceDownMax = FloatCalcHelper.SizeAddOffset(msgContent[10], GlobalValues.VisionOffsetMap["LineTraceDownMax"]);
                    string? lineTraceDownMax = msgContent[10];
                    List<int> lineTraceDownMaxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LineTraceDownMaxRule, lineTraceDownMax);
                    Data3D02[6] = CsvHelper.GetNumberValForCsv(lineTraceDownMax);


                    // 线痕数量 12
                    //string? lineTraceCount = FloatCalcHelper.SizeAddOffset(msgContent[11], GlobalValues.VisionOffsetMap["LineTraceCount"]);
                    string? lineTraceCount = msgContent[11];
                    List<int> lineTraceCountLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LineTraceCountRule, lineTraceCount);
                    Data3D02[7] = CsvHelper.GetNumberValForCsv(lineTraceCount);

                    GlobalValues.WaferData3d01[waferId] = Data3D01;
                    GlobalValues.WaferData3D02[waferId] = Data3D02;

                    if (!GlobalValues.ModuleIsShield.Contains("3D"))
                    {
                        if (thicknessAverLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data01"] = thicknessAverLevel;
                        }
                        if (TTVLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data02"] = TTVLevel;

                        }
                        if (lineTraceMaxLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data03"] = lineTraceMaxLevel;

                        }
                        if (warpingLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data04"] = warpingLevel;
                        }
                        if (thicknessMinLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data05"] = thicknessMinLevel;
                        }
                        if (thicknessMaxLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data06"] = thicknessMaxLevel;
                        }
                        if (isDenseLineLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data07"] = isDenseLineLevel;
                        }
                        if (lineTraceUpNumLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data08"] = lineTraceUpNumLevel;
                        }
                        if (lineTraceUpMaxLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data09"] = lineTraceUpMaxLevel;
                        }
                        if (lineTraceDownNumLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data10"] = lineTraceDownNumLevel;
                        }
                        if (lineTraceDownMaxLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data11"] = lineTraceDownMaxLevel;
                        }
                        if (lineTraceCountLevel.Count > 0)
                        {
                            levelMap[$"{pcName}_data12"] = lineTraceCountLevel;
                        }
                    }

                    logInfo = $"{_clientName} 解析消息内容: 平均厚度(Lv):{thicknessAver}({thicknessAverLevel.ToString<int>()}),TTV(Lv):{TTV}({TTVLevel.ToString<int>()})," +
                       $"线痕最大值(Lv):{lineTraceMax}({lineTraceMaxLevel.ToString<int>()}), 翘曲(Lv):{warping}({warpingLevel.ToString<int>()}),最小厚度(Lv):{thicknessMin}({thicknessMinLevel.ToString<int>()})\n" +
                       $"最大厚度(Lv):{thicknessMax}({thicknessMaxLevel.ToString<int>()}),是否密集线痕(Lv):{isDenseLine}({isDenseLineLevel.ToString<int>()})," +
                       $"上线痕数量(Lv):{lineTraceUpNum}({lineTraceUpNumLevel.ToString<int>()})" +
                       $"上线痕数量最大值(Lv):{lineTraceUpMax}({lineTraceUpMaxLevel.ToString<int>()}),下线痕数量(Lv):{lineTraceDownNum}({lineTraceDownNumLevel.ToString<int>()})," +
                       $"下线痕数量最大值(Lv):{lineTraceDownMax}({lineTraceDownMaxLevel.ToString<int>()})," +
                       $"线痕数量(Lv):{lineTraceCount}({lineTraceCountLevel.ToString<int>()})";
                }

                else if (pcName == "RightEdge" || pcName == "FrontEdge" || pcName == "BackEdge" || pcName == "LeftEdge")
                {
                    string[] dataEdgeBreak;
                    if (GlobalValues.WaferDataEdgeBreak.ContainsKey(waferId))
                    {
                        dataEdgeBreak = GlobalValues.WaferDataEdgeBreak[waferId];
                    }
                    else
                    {
                        dataEdgeBreak = new string[GlobalValues.EdgeBreakFrontTitle.Length + GlobalValues.EdgeBreakBackTitle.Length + GlobalValues.EdgeBreakLeftTitle.Length + GlobalValues.EdgeBreakRightTitle.Length];
                        Array.Fill(dataEdgeBreak, string.Empty);
                    }

                    switch (pcName)
                    {
                        // 1. 前崩边数据内容
                        case "FrontEdge":
                            // 前崩边有无 1
                            string? frontEdgeBreakExist = msgContent[0];
                            List<int> frontEdgeBreakExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.FrontEdgeBreakExistRule, frontEdgeBreakExist);
                            dataEdgeBreak[0] = frontEdgeBreakExist.Equals("0") ? "无" : "有";


                            // 前崩边数量 2
                            string? frontEdgeBreakNum = msgContent[1];
                            List<int> frontEdgeBreakNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.FrontEdgeBreakNumRule, frontEdgeBreakNum);
                            dataEdgeBreak[1] = CsvHelper.GetNumberValForCsv(frontEdgeBreakNum);

                            // 前崩边面积 3
                            string? frontEdgeBreakArea = msgContent[2];
                            List<int> frontEdgeBreakAreaLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.FrontEdgeBreakAreaRule, frontEdgeBreakArea);
                            dataEdgeBreak[2] = CsvHelper.GetNumberValForCsv(frontEdgeBreakArea);

                            if (!GlobalValues.ModuleIsShield.Contains("前崩"))
                            {
                                if (frontEdgeBreakExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data1"] = frontEdgeBreakExistLevel;
                                }
                                if (frontEdgeBreakNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data2"] = frontEdgeBreakNumLevel;
                                }
                                if (frontEdgeBreakAreaLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data3"] = frontEdgeBreakAreaLevel;
                                }
                            }

                            logInfo = $"{_clientName} 解析消息内容: " +
                                            $"前崩边有无(Lv):{frontEdgeBreakExist}({frontEdgeBreakExistLevel.ToString<int>()})," +
                                            $"前崩边数量(Lv):{frontEdgeBreakNum}({frontEdgeBreakNumLevel.ToString<int>()})," +
                                            $"前崩边面积(Lv):{frontEdgeBreakArea}({frontEdgeBreakAreaLevel.ToString<int>()})";
                            break;
                        // 2. 后崩边数据内容
                        case "BackEdge":
                            // 后崩边有无
                            string? backEdgeBreakExist = msgContent[0];
                            List<int> backEdgeBreakExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.BackEdgeBreakExistRule, backEdgeBreakExist);
                            dataEdgeBreak[3] = backEdgeBreakExist.Equals("0") ? "无" : "有";

                            // 后崩边数量
                            string? backEdgeBreakNum = msgContent[1];
                            List<int> backEdgeBreakNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.BackEdgeBreakNumRule, backEdgeBreakNum);
                            dataEdgeBreak[4] = CsvHelper.GetNumberValForCsv(backEdgeBreakNum);

                            // 后崩边面积
                            string? backEdgeBreakArea = msgContent[2];
                            List<int> backEdgeBreakAreaLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.BackEdgeBreakAreaRule, backEdgeBreakArea);
                            dataEdgeBreak[5] = CsvHelper.GetNumberValForCsv(backEdgeBreakArea);

                            if (!GlobalValues.ModuleIsShield.Contains("后崩"))
                            {
                                if (backEdgeBreakExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data2"] = backEdgeBreakExistLevel;
                                }
                                if (backEdgeBreakNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data1"] = backEdgeBreakNumLevel;
                                }
                                if (backEdgeBreakAreaLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data3"] = backEdgeBreakAreaLevel;
                                }
                            }

                            logInfo = $"{_clientName} 解析消息内容: " +
                                            $"后崩边有无(Lv):{backEdgeBreakExist}({backEdgeBreakExistLevel.ToString<int>()})," +
                                            $"后崩边数量(Lv):{backEdgeBreakNum}({backEdgeBreakNumLevel.ToString<int>()})," +
                                            $"后崩边面积(Lv):{backEdgeBreakArea}({backEdgeBreakAreaLevel.ToString<int>()})";
                            break;

                        // 3. 左崩边数据内容
                        case "LeftEdge":
                            // 左崩边有无 1
                            string? leftEdgeBreakExist = msgContent[0];
                            List<int> leftEdgeBreakExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftEdgeBreakExistRule, leftEdgeBreakExist);
                            dataEdgeBreak[6] = leftEdgeBreakExist.Equals("0") ? "无" : "有";

                            // 左崩边数量 2
                            string? leftEdgeBreakNum = msgContent[1];
                            List<int> leftEdgeBreakNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftEdgeBreakNumRule, leftEdgeBreakNum);
                            dataEdgeBreak[7] = CsvHelper.GetNumberValForCsv(leftEdgeBreakNum);

                            // 左表崩有无 3
                            string? leftSurfaceBreakExist = msgContent[2];
                            List<int> leftSurfaceBreakExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftSurfaceBreakExistRule, leftSurfaceBreakExist);
                            dataEdgeBreak[8] = leftSurfaceBreakExist.Equals("0") ? "无" : "有";

                            // 左表崩数量 4
                            string? leftSurfaceBreakNum = msgContent[3];
                            List<int> leftSurfaceBreakNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.LeftSurfaceBreakNumRule, leftSurfaceBreakNum);
                            dataEdgeBreak[9] = CsvHelper.GetNumberValForCsv(leftSurfaceBreakNum);

                            if (!GlobalValues.ModuleIsShield.Contains("左崩"))
                            {
                                if (leftEdgeBreakExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data1"] = leftEdgeBreakExistLevel;
                                }
                                if (leftEdgeBreakNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data2"] = leftEdgeBreakNumLevel;
                                }
                                if (leftSurfaceBreakExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data3"] = leftSurfaceBreakExistLevel;
                                }
                                if (leftSurfaceBreakNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data4"] = leftSurfaceBreakNumLevel;
                                }
                            }

                            logInfo = $"{_clientName} 解析消息内容: 左崩边有无(Lv):{leftEdgeBreakExist}({leftEdgeBreakExistLevel.ToString<int>()})," +
                                            $"左崩边数量(Lv):{leftEdgeBreakNum}({leftEdgeBreakNumLevel.ToString<int>()})," +
                                            $"左表崩有无(Lv):{leftSurfaceBreakExist}({leftSurfaceBreakExistLevel.ToString<int>()})," +
                                            $"左表崩数量(Lv):{leftSurfaceBreakNum}({leftSurfaceBreakNumLevel.ToString<int>()})";
                            break;
                        // 4. 右崩边数据
                        case "RightEdge":
                            // 右崩边有无 1
                            string? rightEdgeBreakExist = msgContent[0];
                            List<int> rightEdgeBreakExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightEdgeBreakExistRule, rightEdgeBreakExist);
                            dataEdgeBreak[10] = rightEdgeBreakExist.Equals("0") ? "无" : "有";

                            // 右崩边数量 2
                            string? rightEdgeBreakNum = msgContent[1];
                            List<int> rightEdgeBreakNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightEdgeBreakNumRule, rightEdgeBreakNum);
                            dataEdgeBreak[11] = CsvHelper.GetNumberValForCsv(rightEdgeBreakNum);

                            // 右表崩有无 3
                            string? rightSurfaceBreakExist = msgContent[2];
                            List<int> rightSurfaceBreakExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightSurfaceBreakExistRule, rightSurfaceBreakExist);
                            dataEdgeBreak[12] = rightSurfaceBreakExist.Equals("0") ? "无" : "有";

                            // 右表崩数量 4
                            string? rightSurfaceBreakNum = msgContent[3];
                            List<int> rightSurfaceBreakNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.RightSurfaceBreakNumRule, rightSurfaceBreakNum);
                            dataEdgeBreak[13] = CsvHelper.GetNumberValForCsv(rightSurfaceBreakNum);

                            if (!GlobalValues.ModuleIsShield.Contains("右崩"))
                            {
                                if (rightEdgeBreakExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data1"] = rightEdgeBreakExistLevel;
                                }
                                if (rightEdgeBreakNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data2"] = rightEdgeBreakNumLevel;
                                }
                                if (rightSurfaceBreakExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data3"] = rightSurfaceBreakExistLevel;
                                }
                                if (rightSurfaceBreakNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data4"] = rightSurfaceBreakNumLevel;
                                }
                            }

                            logInfo = $"{_clientName} 解析消息内容: 右崩边有无(Lv):{rightEdgeBreakExist}({rightEdgeBreakExistLevel.ToString<int>()})," +
                                            $"右崩边数量(Lv):{rightEdgeBreakNum}({rightEdgeBreakNumLevel.ToString<int>()})," +
                                            $"右表崩有无(Lv):{rightSurfaceBreakExist}({rightSurfaceBreakExistLevel.ToString<int>()})," +
                                            $"右表崩数量(Lv):{rightSurfaceBreakNum}({rightSurfaceBreakNumLevel.ToString<int>()})";
                            break;
                        default:
                            logInfo = $"崩边工位({pcName})消息解析错误,相机编号错误,收到的相机编号: {cameraNum},编号有效值:(0,1,2,3)";
                            break;
                    }
                    GlobalValues.WaferDataEdgeBreak[waferId] = dataEdgeBreak; // 崩边工位数据更新.
                }

                else if (pcName == "SmuDown" || pcName == "SmuUp")
                {
                    string[] dataSumdge;
                    if (GlobalValues.WaferDataSumdge.ContainsKey(waferId))
                    {
                        dataSumdge = GlobalValues.WaferDataSumdge[waferId];
                    }
                    else
                    {
                        dataSumdge = new string[GlobalValues.SumdgeUpTitle.Length + GlobalValues.SumdgeDownTitle.Length];
                        Array.Fill(dataSumdge, string.Empty);
                    }
                    // 脏污工位数据
                    switch (cameraNum)
                    {
                        case "0":
                            // 下脏污有无 1
                            string? sumdgeDownExist = msgContent[0];
                            List<int> sumdgeDownExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeDownExistRule, sumdgeDownExist);
                            dataSumdge[6] = sumdgeDownExist.Equals("0") ? "无" : "有";

                            // 下脏污面积 2
                            string? sumdgeDownArea = msgContent[1];
                            List<int> sumdgeDownAreaLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeDownAreaRule, sumdgeDownArea);
                            dataSumdge[7] = CsvHelper.GetNumberValForCsv(sumdgeDownArea);


                            // 下脏污数量 3
                            string? sumdgeDownNum = msgContent[2];
                            List<int> sumdgeDownNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeDownNumRule, sumdgeDownNum);
                            dataSumdge[8] = CsvHelper.GetNumberValForCsv(sumdgeDownNum);


                            // 添加是否反向指标
                            dataSumdge[9] = "否";


                            // 下脏污缺口有无 6 
                            string? holeExistDown = msgContent[5];
                            List<int> holeExistDownLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.HoleExistDownRule, holeExistDown);
                            dataSumdge[10] = holeExistDown.Equals("0") ? "无" : "有";

                            // 下脏污穿孔有无 4
                            string? sumdgeDownHoleExist = msgContent[3];
                            List<int> sumdgeDownHoleExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeDownHoleExistRule, sumdgeDownHoleExist);
                            dataSumdge[11] = sumdgeDownHoleExist.Equals("0") ? "无" : "有";


                            // 下脏污穿孔数量(没有对应检测规则) 5
                            string? sumdgeDownHoleNum = msgContent[4];
                            List<int> sumdgeDownHoleNumLevel = new List<int>();

                            // 下脏污孔洞数量(没有对应检测规则,直接返回空列表)  7 
                            string? holeNumDown = msgContent[6];
                            List<int> holeNumDownLevel = new List<int>();



                            if (!GlobalValues.ModuleIsShield.Contains("下脏污"))
                            {
                                if (sumdgeDownExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data1"] = sumdgeDownExistLevel;
                                }
                                if (sumdgeDownAreaLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data2"] = sumdgeDownAreaLevel;
                                }
                                if (sumdgeDownNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data3"] = sumdgeDownNumLevel;
                                }
                                if (sumdgeDownHoleExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data4"] = sumdgeDownHoleExistLevel;
                                }
                                if (sumdgeDownHoleNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data5"] = sumdgeDownHoleNumLevel;
                                }
                                if (holeExistDownLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data6"] = holeExistDownLevel;
                                }
                                if (holeNumDownLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data7"] = holeNumDownLevel;
                                }

                            }

                            logInfo = $"{_clientName} 解析消息内容: 下脏污有无(Lv):{sumdgeDownExist}({sumdgeDownExistLevel.ToString<int>()})," +
                                           $"下脏污面积(Lv):{sumdgeDownArea}({sumdgeDownAreaLevel.ToString<int>()})," +
                                           $"下脏污数量(Lv):{sumdgeDownNum}({sumdgeDownNumLevel.ToString<int>()})," +
                                           $"下脏污数量(Lv):{sumdgeDownNum}({sumdgeDownNumLevel.ToString<int>()})," +
                                           $"下脏污穿孔有无(Lv):{sumdgeDownHoleExist}({sumdgeDownHoleExistLevel.ToString<int>()})," +
                                           $"下脏污穿孔数量(Lv):{sumdgeDownHoleNum}({sumdgeDownHoleNumLevel.ToString<int>()})," +
                                           $"下脏污缺口有无(Lv):{holeExistDown}({holeExistDownLevel.ToString<int>()})," +
                                           $"下脏污孔洞数量(Lv):{holeNumDown}({holeNumDownLevel.ToString<int>()})";
                            break;
                        // 2. 上脏污工位数据内容
                        case "1":
                            // 脏污上_有无 1
                            string? sumdgeUpExist = msgContent[0];
                            List<int> sumdgeUpExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeUpExistRule, sumdgeUpExist);
                            dataSumdge[0] = sumdgeUpExist.Equals("0") ? "无" : "有";


                            // 脏污上_面积 2
                            string? smudgeUpArea = msgContent[1];
                            List<int> smudgeUpAreaLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeUpAreaRule, smudgeUpArea);
                            dataSumdge[1] = CsvHelper.GetNumberValForCsv(smudgeUpArea);


                            // 脏污上_数量 3
                            string? sumdgeUpNum = msgContent[2];
                            List<int> sumdgeUpNumLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeUpNumRule, sumdgeUpNum);
                            dataSumdge[2] = CsvHelper.GetNumberValForCsv(sumdgeUpNum);


                            // 是否反向,没有收到数据默认给0
                            dataSumdge[3] = "否";



                            // 脏污上_缺口有无 6 (使用规则和脏污下相同)
                            string? holeExistUp = msgContent[5];
                            List<int> holeExistUpLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.HoleExistUpRule, holeExistUp);
                            dataSumdge[4] = holeExistUp.Equals("0") ? "无" : "有";


                            // 脏污上_穿孔有无 4
                            string? sumdgeUpHoleExist = msgContent[3];
                            List<int> sumdgeUpHoleExistLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SumdgeUpHoleExistRule, sumdgeUpHoleExist);
                            dataSumdge[5] = sumdgeUpHoleExist.Equals("0") ? "无" : "有";


                            // 脏污上_穿孔数量 5
                            string? sumdgeUpHoleNum = msgContent[4];
                            List<int> sumdgeUpHoleNumLevel = new List<int>();


                            // 脏污上_孔洞数量 7 (使用规则和脏污下相同)
                            string? holeNumUp = msgContent[6];
                            List<int> holeNumUpLevel = new List<int>();




                            if (!GlobalValues.ModuleIsShield.Contains("上脏污"))
                            {
                                if (sumdgeUpExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data1"] = sumdgeUpExistLevel;
                                }
                                if (smudgeUpAreaLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data2"] = smudgeUpAreaLevel;
                                }
                                if (sumdgeUpNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data3"] = sumdgeUpNumLevel;
                                }
                                if (sumdgeUpHoleExistLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data4"] = sumdgeUpHoleExistLevel;

                                }
                                if (sumdgeUpHoleNumLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data5"] = sumdgeUpHoleNumLevel;
                                }
                                if (holeExistUpLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data6"] = holeExistUpLevel;
                                }
                                if (holeNumUpLevel.Count > 0)
                                {
                                    levelMap[$"{_clientName}_data7"] = holeNumUpLevel;
                                }
                            }

                            logInfo = $"{_clientName} 解析消息内容: 上脏污有无(Lv):{sumdgeUpExist}({sumdgeUpExistLevel.ToString<int>()})," +
                                           $"上脏污面积(Lv):{smudgeUpArea}({smudgeUpAreaLevel.ToString<int>()})," +
                                           $"上脏污数量(Lv):{sumdgeUpNum}({sumdgeUpNumLevel.ToString<int>()})," +
                                           $"上脏污穿孔有无(Lv):{sumdgeUpHoleExist}({sumdgeUpHoleExistLevel.ToString<int>()})," +
                                           $"上脏污穿孔数量(Lv):{sumdgeUpHoleNum}({sumdgeUpHoleNumLevel.ToString<int>()})," +
                                           $"上脏污缺口有无(Lv):{holeExistUp}({holeExistUpLevel.ToString<int>()})," +
                                           $"上脏污孔洞数量(Lv):{holeNumUp}({holeNumUpLevel.ToString<int>()})";
                            break;
                        default:
                            logInfo = $"脏污工位({pcName})消息解析错误,相机编号错误,收到的相机编号: {cameraNum},编号有效值:(0,1)";
                            break;
                    }

                    GlobalValues.WaferDataSumdge[waferId] = dataSumdge; // 脏污工位数据更新
                }

                else if (pcName == "Subfi")
                {
                    string[] subfissureData = new string[GlobalValues.SubfissureTitle.Length];

                    // 前隐裂有无 1
                    string? subfissureExist01 = msgContent[0];
                    List<int> subfissureExist01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureExist01Rule, subfissureExist01);
                    subfissureData[0] = subfissureExist01.Equals("0") ? "无" : "有";

                    // 前隐裂面积 2
                    string? subfissureArea01 = msgContent[1];
                    List<int> subfissureArea01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureArea01Rule, subfissureArea01);
                    subfissureData[1] = CsvHelper.GetNumberValForCsv(subfissureArea01);


                    // 前隐裂数量 3
                    string? subfissureNum01 = msgContent[2];
                    List<int> subfissureNum01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureNum01Rule, subfissureNum01);
                    subfissureData[2] = CsvHelper.GetNumberValForCsv(subfissureNum01);


                    // 前隐裂_崩边有无 4
                    string? subfissureBreakExist01 = msgContent[3];
                    List<int> subfissureBreakExist01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureBreakExist01Rule, subfissureBreakExist01);
                    subfissureData[3] = subfissureBreakExist01.Equals("0") ? "无" : "有";


                    // 前隐裂_崩边面积 5
                    string? subfissureBreakArea01 = msgContent[4];
                    List<int> subfissureBreakArea01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureBreakArea01Rule, subfissureBreakArea01);
                    subfissureData[4] = CsvHelper.GetNumberValForCsv(subfissureBreakArea01);


                    // 前隐裂_崩边数量 6
                    string? subfissureBreakNum01 = msgContent[5];
                    List<int> subfissureBreakNum01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureBreakNum01Rule, subfissureBreakNum01);
                    subfissureData[5] = CsvHelper.GetNumberValForCsv(subfissureBreakNum01);



                    // 前隐裂_孔洞有无 7
                    string? subfissureHoleExist01 = msgContent[6];
                    List<int> subfissureHoleExist01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureHoleExist01Rule, subfissureHoleExist01);
                    subfissureData[6] = subfissureHoleExist01.Equals("0") ? "无" : "有";


                    // 前隐裂_孔洞数量 8
                    string? subfissureHoleNum01 = msgContent[7];
                    List<int> subfissureHoleNum01Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureHoleNum01Rule, subfissureHoleNum01);
                    subfissureData[7] = CsvHelper.GetNumberValForCsv(subfissureHoleNum01);


                    // 后隐裂有无 9
                    string? subfissureExist02 = msgContent[8];
                    List<int> subfissureExist02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureExist02Rule, subfissureExist02);
                    subfissureData[8] = subfissureExist02.Equals("0") ? "无" : "有";


                    // 后隐裂面积 10
                    string? subfissureArea02 = msgContent[9];
                    List<int> subfissureArea02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureArea02Rule, subfissureArea02);
                    subfissureData[9] = CsvHelper.GetNumberValForCsv(subfissureArea02);


                    // 后隐裂数量 11
                    string? subfissureNum02 = msgContent[10];
                    List<int> subfissureNum02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureNum02Rule, subfissureNum02);
                    subfissureData[10] = CsvHelper.GetNumberValForCsv(subfissureNum02);


                    // 后隐裂_崩边有无 12
                    string? subfissureBreakExist02 = msgContent[11];
                    List<int> subfissureBreakExist02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureBreakExist02Rule, subfissureBreakExist02);
                    subfissureData[11] = subfissureBreakExist02.Equals("0") ? "无" : "有";


                    // 后隐裂_崩边面积 13
                    string? subfissureBreakArea02 = msgContent[12];
                    List<int> subfissureBreakArea02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureBreakArea02Rule, subfissureBreakArea02);
                    subfissureData[12] = CsvHelper.GetNumberValForCsv(subfissureBreakArea02);


                    // 后隐裂_崩边数量 14
                    string? subfissureBreakNum02 = msgContent[13];
                    List<int> subfissureBreakNum02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureBreakNum02Rule, subfissureBreakNum02);
                    subfissureData[13] = CsvHelper.GetNumberValForCsv(subfissureBreakNum02);


                    // 后隐裂_孔洞有无 15
                    string? subfissureHoleExist02 = msgContent[14];
                    List<int> subfissureHoleExist02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureHoleExist02Rule, subfissureHoleExist02);
                    subfissureData[14] = subfissureHoleExist02.Equals("0") ? "无" : "有";


                    // 后隐裂_孔洞数量 16
                    string? subfissureHoleNum02 = msgContent[15];
                    List<int> subfissureHoleNum02Level = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.SubfissureHoleNum02Rule, subfissureHoleNum02);
                    subfissureData[15] = CsvHelper.GetNumberValForCsv(subfissureHoleNum02);

                    GlobalValues.WaferDataSubfissure[waferId] = subfissureData; // 隐裂数据也添加完毕.


                    if (!GlobalValues.ModuleIsShield.Contains("隐裂"))
                    {
                        if (subfissureExist01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data1"] = subfissureExist01Level;
                        }
                        if (subfissureArea01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data2"] = subfissureArea01Level;
                        }
                        if (subfissureNum01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data3"] = subfissureNum01Level;
                        }
                        if (subfissureBreakExist01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data4"] = subfissureBreakExist01Level;
                        }
                        if (subfissureBreakArea01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data5"] = subfissureBreakArea01Level;
                        }
                        if (subfissureBreakNum01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data6"] = subfissureBreakNum01Level;
                        }
                        if (subfissureHoleExist01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data7"] = subfissureHoleExist01Level;
                        }
                        if (subfissureHoleNum01Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data8"] = subfissureHoleNum01Level;
                        }

                        if (subfissureExist02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data9"] = subfissureExist02Level;
                        }
                        if (subfissureArea02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data10"] = subfissureArea02Level;
                        }
                        if (subfissureNum02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data11"] = subfissureNum02Level;
                        }
                        if (subfissureBreakExist02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data12"] = subfissureBreakExist02Level;
                        }
                        if (subfissureBreakArea02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data13"] = subfissureBreakArea02Level;
                        }
                        if (subfissureBreakNum02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data14"] = subfissureBreakNum02Level;
                        }
                        if (subfissureHoleExist02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data15"] = subfissureHoleExist02Level;
                        }
                        if (subfissureHoleNum02Level.Count > 0)
                        {
                            levelMap[$"{_clientName}_data16"] = subfissureHoleNum02Level;
                        }
                    }

                    logInfo = $"{_clientName} 解析消息内容: 前隐裂有无(Lv):{subfissureExist01}({subfissureExist01Level.ToString<int>()})," +
                                        $"前隐裂面积(Lv):{subfissureArea01}({subfissureArea01Level.ToString<int>()})," +
                                        $"前隐裂数量(Lv):{subfissureNum01}({subfissureNum01Level.ToString<int>()})," +
                                        $"前隐裂_崩边有无(Lv):{subfissureBreakExist01}({subfissureBreakExist01Level.ToString<int>()})," +
                                        $"前隐裂_崩边面积(Lv):{subfissureBreakArea01}({subfissureBreakArea01Level.ToString<int>()})," +
                                        $"前隐裂_崩边数量(Lv):{subfissureBreakNum01}({subfissureBreakNum01Level.ToString<int>()})\n " +
                                        $"前隐裂_孔洞有无(Lv):{subfissureHoleExist01}({subfissureHoleExist01Level.ToString<int>()})," +
                                        $"前隐裂_孔洞数量(Lv):{subfissureHoleNum01}({subfissureHoleNum01Level.ToString<int>()}), " +
                                        $"后隐裂有无(Lv):{subfissureExist02}({subfissureExist02Level.ToString<int>()})," +
                                        $"后隐裂面积(Lv):{subfissureArea02}({subfissureArea02Level.ToString<int>()})," +
                                        $"后隐裂数量(Lv):{subfissureNum02}({subfissureNum02Level.ToString<int>()})," +
                                        $"后隐裂_崩边有无(Lv):{subfissureBreakExist02}({subfissureBreakExist02Level.ToString<int>()})\n " +
                                        $"后隐裂_崩边面积(Lv):{subfissureBreakArea02}({subfissureBreakArea02Level.ToString<int>()})," +
                                        $"后隐裂_崩边数量(Lv):{subfissureBreakNum02}({subfissureBreakNum02Level.ToString<int>()})," +
                                        $"后隐裂_孔洞有无(Lv):{subfissureHoleExist02}({subfissureHoleExist02Level.ToString<int>()})," +
                                        $"后隐裂_孔洞数量(Lv):{subfissureHoleNum02}({subfissureHoleNum02Level.ToString<int>()})";
                }
                else
                {
                    logInfo = $"PC名称错误,解析到的PC名称为{pcName},有效PC值为:(PC1,PC2,PC3,PC4,PC5)";
                }
                // 1. 消息写入专门创建一个日志文件负责存放消息.
                if (_clientName!.Equals("崩边隐裂") && (pcName != "Subfi"))
                {
                    LogHelper.WriteLogEdgeBreak(LogType.Info, logInfo);
                }
                else if (_clientName!.Equals("脏污"))
                {
                    LogHelper.WriteLogSumdge(LogType.Info, logInfo);
                }
                else if (_clientName!.Equals("3D"))
                {
                    LogHelper.WriteLog3D(LogType.Info, logInfo);
                }
                else if (_clientName!.Equals("尺寸"))
                {
                    LogHelper.WriteLogSize(LogType.Info, logInfo);
                }
                else if (_clientName!.Equals("崩边隐裂") && (pcName == "Subfi"))
                {
                    LogHelper.WriteLogSubfissure(LogType.Info, logInfo);
                    DataResult res = MsgParseHelper.UpdateWaferIdSummaryTask(waferId);
                    if (!res.State)
                    {
                        LogHelper.WriteLog(LogType.Warn, $"隐裂工位数据更新时间加入到全部变量中失败: {res.Message}");
                    }
                }
                else
                {
                    LogHelper.WriteLog(LogType.Info, logInfo);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
        }

        // 根据厚度计算和保存电阻率的值
        private void CalcAndKeepResistivityWithThickness(string waferId, double thickness)
        {
            //1. 先根据这个Id去获取电阻率,如果没有值
            if (GlobalValues.ResistivityValMap.ContainsKey(waferId))
            {
                var data = GlobalValues.ResistivityValMap[waferId];
                GlobalValues.ResistivityValMap.Remove(waferId); // 将这个值移除
                string rstMaxShow = GetFinalValByKb(data.Item1, thickness);
                string rstMinShow = GetFinalValByKb(data.Item2, thickness);
                string rstAverShow = GetFinalValByKb(data.Item3, thickness);
                List<int> maxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ResistivityMaxRule, rstMaxShow);
                List<int> minLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ResistivityMinRule, rstMinShow);
                List<int> averLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ResistivityAverRule, rstAverShow);

                Dictionary<string, List<int>> levelMap = new Dictionary<string, List<int>>();
                // 如果已经存在,就不用赋值了
                if (GlobalValues.WaferIdLevelDictionary.ContainsKey(waferId))
                {
                    levelMap = GlobalValues.WaferIdLevelDictionary[waferId];
                }
                else
                {
                    GlobalValues.WaferIdLevelDictionary[waferId] = levelMap;
                }

                // 电阻率的名称
                string rstClientName = "电阻率";

                if (!GlobalValues.ModuleIsShield.Contains(rstClientName!))
                {
                    if (maxLevel.Count > 0)
                    {
                        levelMap[$"{rstClientName}_1"] = maxLevel;
                    }
                    if (minLevel.Count > 0)
                    {
                        levelMap[$"{rstClientName}_2"] = minLevel;
                    }
                    if (averLevel.Count > 0)
                    {
                        levelMap[$"{rstClientName}_3"] = averLevel;
                    }
                }

                // 数据库更新的时候,查询的字段(根据产品流水号和晶棒编号)
                // 数据库更新的时候,查询的字段(根据流水号产品Id和晶棒编号)
                List<string> queryFields = new List<string>()
                {
                    "WaferId","CrystalNumber","CutNumber"
                };

                List<string> queryVals = new List<string>()
                {
                    waferId,GlobalValues.CrystalNumberCurrent!,GlobalValues.CrystalNumberCurrent!
                };


                List<string> updateFields = new List<string>();
                List<string> updateVals = new List<string>();
                updateFields.Add("ResistivityAver");
                updateVals.Add(rstAverShow);
                updateFields.Add("ResistivityMax");
                updateVals.Add(rstMaxShow);
                updateFields.Add("ResistivityMin");
                updateVals.Add(rstMinShow);

                // 数据保存到全年局变量中去
                string[] dataResistivity = new string[GlobalValues.ResistivityTitle.Length];
                dataResistivity[0] = CsvHelper.GetNumberValForCsv(rstAverShow);
                dataResistivity[1] = CsvHelper.GetNumberValForCsv(rstMaxShow);
                dataResistivity[2] = CsvHelper.GetNumberValForCsv(rstMinShow);
                GlobalValues.WaferDataResistivity[waferId] = dataResistivity;

                // 保存到全局变量中,方便国产电阻率使用
                //string[] naponsVal = new string[] { waferId, thicknessVal.ToString(), resistivityAverShow, resistivityMaxShow, resistivityMinShow, pnVal };
                //GlobalValues.NaponsResistivityQueue.Enqueue(naponsVal); // 放入队列中.

                //Task.Run(() =>
                //{
                //    DataResult res = LocalDataAccess.UpdateWaferDetectedDetailTb(queryFields, queryVals, updateFields, updateVals);
                //    if (!res.State)
                //    {
                //        LogHelper.WriteLog(LogType.Warn, $"电阻率数据写入到数据库中失败: {res.Message},此时的updateFields = {string.Join(',', updateFields)},updateVals = {string.Join(',', updateVals)}");
                //    }
                //});
                DataResult res = MsgParseHelper.UpdateWaferIdSummaryTask(waferId);
                if (!res.State)
                {
                    LogHelper.WriteLog(LogType.Warn, $"电阻率流水号对应更新时间添加到全局变量中失败: {res.Message}");
                }

            }
            else
            {
                LogHelper.WriteLog(LogType.Warn, $"流水号:{waferId},对应的电阻率的值没有,电阻率数据丢失");
            }
        }

        /// <summary>
        /// 根据K和B以及厚度去计算电阻率的值
        /// </summary>
        /// <param name="resistivityMax"></param>
        /// <param name="thicknessVal"></param>
        /// <returns></returns>
        private string GetFinalValByKb(double val, double thicknessVal)
        {
            try
            {
                double[] args = GlobalValues.VisionOffsetMap["NaponsNc"];
                return (args[0] * thicknessVal * val * 0.0001 + args[1]).ToString("f3");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Fatal, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
                return "0";
            }
        }


        /// <summary>
        ///  将当前的识别结果添加到全局变量中,以便每次识别结束保存到csv文件中去.
        /// </summary>
        /// <param name="waferId"></param>
        /// <param name="updateVals"></param>


        /// <summary>
        /// 将错误消息写入到等级类型中
        /// 00: 3D工位误触发
        /// 01:  连片
        /// 02: 反向
        /// 03: 遮挡
        /// 04: 碎片
        /// 05: 错位
        /// 06: PLC通讯异常
        /// 07: 3D数据错乱
        /// 
        /// 对应写入给Plc的异常位置为1,2,3,4,5,6,7,8
        /// 
        /// </summary>
        /// <param name="errorCode"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void WriteErrorLevelToWaferLevel(string waferId, string errorCode)
        {
            Dictionary<string, List<int>> levelMap = new Dictionary<string, List<int>>();
            ushort plcErrorVal = 0;
            // 如果已经存在了,就不用赋值了.
            if (GlobalValues.WaferIdLevelDictionary.ContainsKey(waferId))
            {
                levelMap = GlobalValues.WaferIdLevelDictionary[waferId];
            }
            else
            {
                GlobalValues.WaferIdLevelDictionary[waferId] = levelMap;
            }
            switch (errorCode)
            {
                case "00": // 3D工位误触发
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 36 };
                    plcErrorVal = 1;
                    LogHelper.WriteLog(LogType.Fatal, $"3D工位误触发,对应流水号: {waferId}", errorCode: "P11", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "3D工位误触发";
                    break;
                case "01": // 连片
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 32 };
                    plcErrorVal = 2;
                    LogHelper.WriteLog(LogType.Fatal, $"连片(直流),对应流水号: {waferId}", errorCode: "P14", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "连片";
                    break;
                case "02": // 反向
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 32 };
                    plcErrorVal = 3;
                    LogHelper.WriteLog(LogType.Fatal, $"反向(直流),对应流水号: {waferId}", errorCode: "P15", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "反向";
                    break;
                case "03": // 遮挡
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 33 };
                    plcErrorVal = 4;
                    LogHelper.WriteLog(LogType.Fatal, $"遮挡(直流)报警,对应流水号: {waferId}", errorCode: "P12", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "遮挡";
                    break;
                case "04": // 碎片
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 32 };
                    plcErrorVal = 5;
                    LogHelper.WriteLog(LogType.Fatal, $"碎片报警,对应流水号: {waferId}", errorCode: "P16", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "碎片";
                    break;
                case "05": // 错位
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 34 };
                    plcErrorVal = 6;
                    LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P13", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "错位";
                    if (PlcCommunication.Instance.PlcState.IsOnline!.Equals("已连接"))
                    {
                        PlcCommunication.Instance.PlcLoadControl("Close"); // 
                    }
                    break;
                case "06": // PLC通讯异常
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 35 };
                    plcErrorVal = 7;
                    LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P09", isInsert: true);
                    GlobalValues.VisionErrorWithWaferId[waferId] = "PLC通讯异常";
                    if (PlcCommunication.Instance.PlcState.IsOnline!.Equals("已连接"))
                    {
                        PlcCommunication.Instance.PlcLoadControl("Close"); // 主线停止
                    }
                    break;
                case "07": // 3D数据错乱
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 37 };
                    plcErrorVal = 8;
                    GlobalValues.VisionErrorWithWaferId[waferId] = "3D数据错乱";
                    LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P10", isInsert: true);
                    if (PlcCommunication.Instance.PlcState.IsOnline!.Equals("已连接"))
                    {
                        PlcCommunication.Instance.PlcLoadControl("Close"); // 主线停止
                    }
                    break;
                default:
                    levelMap[MsgErrorHelperPc.GetErrorInfoByCode(errorCode)] = new List<int> { 32 };
                    break;
            }

            // 将这个错误消息发送给PLC,PLC来判定要做什么动作
            if (PlcCommunication.Instance.PlcState.IsOnline!.Equals("已连接"))
            {
                // 告诉PLC视觉异常,让PLC去处理动作
                DataResult plcRes = PlcCommunication.Instance.WriteVisionErrorToPlc(plcErrorVal);
                if (!plcRes.State)
                {
                    LogHelper.WriteLog(LogType.Exception, $"视觉异常信息写入到Plc失败: {plcRes.Message}");
                }
            }
        }
    }
}
